home *** CD-ROM | disk | FTP | other *** search
/ Celestin Apprentice 5 / Apprentice-Release5.iso / Source Code / C++ / Snippets / alias_to_fname / alias_to_fname.cc
Encoding:
C/C++ Source or Header  |  1996-04-22  |  5.4 KB  |  132 lines  |  [BINA/hDmp]

  1. /*
  2.  *------------------------------------------------------------------------
  3.         When handling odoc (Open Document), pdoc (Print Document) and
  4. similar AppleEvents, one sometimes needs to know the full directory
  5. path to the document being opened. The "standard" way of going about
  6. this is to obtain FSSpec from the AppleEvent record (or by coercing an
  7. AliasRecord), and use FSSpec's parent directory id to walk up the
  8. folder hierarchy (by repeatedly calling PBGetCatInfoSync())
  9. reconstructing the full path. It works just fine, but kind of tedious:
  10. filling out CInfoPBRec struct is rather messy. Recently I stumbled
  11. upon an easier and shorter way, for a programmer. It's based on two
  12. tricks:
  13.         - AliasRecord gotten from AEDescList of an odoc event record
  14. is a minimal AliasRecord. We need the full record.
  15.         - It's very easy to get volume, folder, file names from the
  16. full AliasRecord. No PBGetCatInfoSync() calls, at least, not by a
  17. programmer.
  18.  
  19.         Again, this technique (code below) would not probably save
  20. too many instructions a CPU has to execute; but it'll definitely help bump
  21. a few lines off the source code. One can also use these tricks to obtain
  22. the full file path from any other AppleEvent pertaining to file(s), or
  23. any AliasRecord or FSSpec for that matter.
  24.  
  25. Converting a minimal alias (say, "pointed" to by an 'alias_handle') to
  26. the full one is a matter of four lines of code:
  27.  
  28.     FSSpec resolved_target;
  29.     Boolean was_changed;
  30.     do_well( ResolveAlias(0,alias_handle,&resolved_target,&was_changed) );
  31.     do_well( UpdateAlias(0,&resolved_target,alias_handle,&was_changed) );
  32.  
  33. The code below defines a function to do the trick, as well as a test
  34. driver to make sure the thing really works.
  35.  
  36. The code has been compiled and tested with CodeWarrior 5-7.
  37. *------------------------------------------------------------------------
  38. */
  39.  
  40. #include <string.h>
  41. #include <stdio.h>
  42. #include <stdlib.h>
  43. #include <assert.h>
  44.                 // Execute a function 'ex' and make sure
  45.                 // it returns noErr
  46. #define do_well(ex) \
  47.   { OSErr err = (ex); if( err != noErr ) \
  48.     fprintf(stderr,"Failed call " #ex " with error %ld at line %ld of `%s'.", \
  49.     err, __LINE__, __FILE__), exit(4); }
  50.  
  51.  
  52.                 // Get a full path from an alias record
  53.                 // Returns a pointer to a static string
  54.                 // Note, alias has to be a full alias
  55.                 // (minimal alias doesn't have directories record)
  56. const char * get_full_path(AliasHandle alias_handle)
  57. {
  58.   static char path[700];        // Full path to return
  59.   Str63 buffer;
  60.                 // Write a volume name at the beginning of
  61.                 // the path
  62.   do_well( GetAliasInfo(alias_handle,asiVolumeName,buffer) );
  63.   memcpy(path,(char *)buffer+1,buffer[0]);
  64.   char * first_col_pos = path + buffer[0];
  65.   *first_col_pos = ':';         // colon after the volume name
  66.   char * after_ldir_pos = first_col_pos+1;
  67.  
  68.                         // Put directory names from the parent upwards
  69.                         // In the string
  70.                         //      Volume_name:Dir3:Dir2:Dir1:
  71.                         // first_col_pos points to the first : after
  72.                         // the volume name, after_ldir_pos points
  73.                         // after the last column. The new directory
  74.                         // retrieved from the alias record is wedged
  75.                         // between the volume name and first_col_pos
  76.   for(register int dir_level=1;;dir_level++)
  77.   {
  78.     do_well( GetAliasInfo(alias_handle,dir_level,buffer) );
  79.     if( buffer[0] == 0 )
  80.       break;            // no more (grand...dad) directories
  81.                         // Move [after_vname_pos,after_ldir_pos)
  82.                         // chunk forward to make room for this
  83.                         // (grand)parent directory
  84.     char * p = after_ldir_pos;
  85.     char * q = after_ldir_pos += buffer[0]+1;   // reserve space for :
  86.     assert( after_ldir_pos < path + sizeof(path) );
  87.     while( p > first_col_pos )
  88.       *--q = *--p;
  89.     p = (char *)buffer+1+buffer[0];     // End of the (grand)parent dir name
  90.     while( q > first_col_pos+1 )
  91.       *--q = *--p;
  92.   }
  93.                 // Get the file name itself and append it to the
  94.                 // end
  95.   do_well( GetAliasInfo(alias_handle,asiAliasName,buffer) );
  96.   assert( after_ldir_pos+buffer[0]+1 < path + sizeof(path) );
  97.   memcpy(after_ldir_pos,(char *)buffer+1,buffer[0]);
  98.   after_ldir_pos[buffer[0]] = '\0';     // Properly terminate the string
  99.  
  100.   return path;
  101. }
  102.  
  103.             // Test driver
  104.             // Since getting an AppleEvent and taking
  105.             // an AliasRecord from it is a bit of a hassle
  106.             // we use a simpler test: convert a full file
  107.             // name into an alias record, and get it back
  108. void main(void)
  109. {
  110.   FSSpec file_spec;
  111.   do_well(FSMakeFSSpec(0,0,"\pA System:SYSTEM FOLDER:HOSTS",&file_spec));
  112.   AliasHandle alias;        // Pretend this alias is from an AppleEvent
  113.   do_well( NewAliasMinimal(&file_spec,&alias) );
  114.   
  115.               // Now do our trick of turning a min alias to a
  116.               // full one (see comments above). Of course we could've
  117.               // made the full alias right upfront above. But in
  118.               // real applications, an alias from an odoc/pdoc/etc
  119.               // AppleEvent is a min one, and we don't get any choice
  120.   {
  121.     FSSpec resolved_target;
  122.     Boolean was_changed;
  123.     do_well( ResolveAlias(0,alias,&resolved_target,&was_changed) );
  124.     do_well( UpdateAlias(0,&resolved_target,alias,&was_changed) );
  125.   }
  126.   
  127.   printf("\nThe full file name obtained from an alias is '%s'\n",
  128.        get_full_path(alias));
  129.  
  130.   DisposHandle((Handle)alias);
  131. }
  132.